package com.baidu.bas.core.view;

import com.baidu.bas.annotation.Erupt;
import com.baidu.bas.annotation.model.English;
import com.baidu.bas.annotation.sub_field.Edit;
import com.baidu.bas.annotation.sub_field.EditType;
import com.baidu.bas.core.util.AnnotationUtil;
import com.baidu.bas.core.util.ReflectUtil;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.google.gson.JsonObject;
import lombok.Data;
import lombok.SneakyThrows;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.baidu.bas.annotation.sub_field.EditType.COMBINE;

/**
 * @author liyuepeng
 * @date 2018-09-29.
 */
@Data
public final class EruptModel implements Cloneable, Serializable {

    private transient Class<?> clazz;

    private transient Erupt erupt;

    private transient Map<String, EruptFieldModel> eruptFieldMap;

    private String eruptName;

    private JsonObject eruptJson;

    private List<EruptFieldModel> eruptFieldModels;

    public static EruptModel of(Class<?> eruptClazz){
        return new EruptModel(eruptClazz);
    }

    public EruptModel(Class<?> eruptClazz) {
        this.clazz = eruptClazz;
        this.erupt = eruptClazz.getAnnotation(Erupt.class);
        this.eruptName = eruptClazz.getSimpleName();
        this.eruptJson = AnnotationUtil.annotationToJsonByReflect(this.erupt);
    }

    private static final PropertyNamingStrategy.SnakeCaseStrategy strategy = new PropertyNamingStrategy.SnakeCaseStrategy();

    public String snakeCaseEruptName(){
        return strategy.translate(clazz.getSimpleName());
    }

    public String asTableName(){
        return this.eruptName.toLowerCase().concat("_");
    }

    @SneakyThrows
    public Object getIdValue(Object obj){
        return ReflectUtil.findClassField(this.getClazz(), this.getErupt().primaryKeyCol()).get(obj);
    }

    /**
     * 多对一的复杂类型
     * @return
     */
    public List<EruptFieldModel> getToOneFields(){
        return this.getEruptFieldModels().stream().filter(field -> {
            Edit edit = field.getEruptField().edit();
            return (edit.type() == EditType.REFERENCE_TREE || edit.type() == EditType.REFERENCE_TABLE || edit.type()==COMBINE);
        }).collect(Collectors.toList());
    }

    public List<EruptFieldModel> getLogicalFields(){
        return eruptFieldModels.stream().filter(EruptFieldModel::isLogicDelete).collect(Collectors.toList());
    }

    public EruptFieldModel getLogicalDeleteField(){
        return eruptFieldModels.stream().filter(EruptFieldModel::isLogicDelete).findFirst().orElse(null);
    }

    /**
     * 获取租户字段
     * @return
     */
    public EruptFieldModel getTenancyField(){
        return eruptFieldModels.stream().filter(EruptFieldModel::isHasTenancy).findFirst().orElse(null);
    }

    /**
     * TODO 支持多个英文字段
     * @return
     */
    public EruptFieldModel getEnglishField(){
        return eruptFieldModels.stream().filter(it->it.getField().getAnnotation(English.class)!=null).findFirst().orElse(null);
    }

    @Override
    public final EruptModel clone() throws CloneNotSupportedException {
        return (EruptModel) super.clone();
    }

}
